package scparser;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;


import lib.common.Constants;
import model.Image;
import model.Scene;
import model.lights.Light;
import model.primitive.Primitive;
import model.shader.Shader;
import scparser.factory.primitiveFactory.FactoryException;
import scparser.factory.sceneFactory.SceneAbstractFactory;
import scparser.factory.sceneFactory.SceneCameraFactory;
import scparser.factory.sceneFactory.SceneImageFactory;
import scparser.factory.sceneFactory.SceneLightFactory;
import scparser.factory.sceneFactory.SceneObjectFactory;
import scparser.factory.sceneFactory.SceneShaderFactory;
import camera.Camera;

public class Parser {
	private static Parser instance;
	
	public static Parser instance() {
		if (instance == null) {
			instance = new Parser();
		}
		return instance;
	}
	
	public Scene parse (String fileName) throws FactoryException  {
		File sceneFile = new File(fileName);
		if (!sceneFile.exists()) {
			throw new FactoryException("file not found: " + sceneFile.getAbsolutePath());
		}
		String line;
		BufferedReader br = null;
		Scene scene = new Scene(new ArrayList<Light>(), new ArrayList<Shader>(), new ArrayList<Primitive>());
		
		SceneAbstractFactory sceneFactory;
		
		try {
			br = new BufferedReader(new FileReader(sceneFile));
			while ((line = br.readLine()) != null) {
				line = line.trim();
				if (line.startsWith(Constants.INCLUDE)) {
					scene = parse(ParserHelper.takeString(line, "include"));
				}
				
				if (!line.equals("") && !line.startsWith(Constants.COMMENT)) {
					if (line.startsWith(Constants.type.object.toString())) {
						sceneFactory =  new SceneObjectFactory(scene);
						scene.addPrimitive((Primitive) sceneFactory.create(br));
						
					} else if (line.startsWith(Constants.type.shader.toString())) {
						sceneFactory = new SceneShaderFactory(scene);
						scene.addShader((Shader) sceneFactory.create(br));
					} else if (line.startsWith(Constants.type.camera.toString())) {
						sceneFactory = new SceneCameraFactory(scene);
						scene.setCamera((Camera)sceneFactory.create(br));
					} else if (line.startsWith(Constants.type.image.toString())) {
						sceneFactory = new SceneImageFactory(scene);
						scene.setImage((Image)sceneFactory.create(br));
					} else if (line.startsWith(Constants.type.light.toString())) {
						sceneFactory = new SceneLightFactory(scene);
						scene.addLight((Light)sceneFactory.create(br));
					} else if (line.startsWith(Constants.type.bucket.toString())) {
						String[] values = ParserHelper.takeString(line, 
								Constants.type.bucket.toString()).trim().split(" ");
						//ignore the second attribute of bucket
						scene.bucket = Integer.parseInt(values[0]);
					}
				}
				
			}
		} catch (IOException e) {
			throw new FactoryException(e.getMessage());
		} finally {
			try {
				br.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		return scene;
	}
}
